home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
ov143b.zip
/
OVVIEW.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-04
|
29KB
|
858 lines
/* 034 23-May-87 ovview.c
Copyright (c) 1987 by Blue Sky Software. All rights reserved.
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ov.h"
#include "overr.h"
#include "menu.h"
#include "direct.h"
#include "strmem.h"
#define H_bar (0xcd)
#define V_bar (179)
#define FSTR_LEN (40) /* max find str length */
#define Vnextch(fh) ((curp < endp) ? *curp++ : vnextch(fh)) /* speed up */
#define Vprevch(fh) ((curp > bufp) ? *--curp : vprevch(fh)) /* buffer access */
extern unsigned char far *curp; /* current char position */
extern unsigned char far *bufp, far *endp; /* buffer begin/end pointers */
static int (*mark_func)(); /* pointer to marker function */
static int nlines; /* # lines displayed on screen */
static unsigned char ascmode; /* true means ascii mode display */
static unsigned char bitmask; /* for 7 or 8 bit display mode */
static int inf; /* handle for file being viewed */
static int margin; /* margin for right/left scrolling */
static long tos; /* top of screen offset in file */
static long markers[5]; /* marker positions */
static char *findstr = NULL; /* string to find in view */
static long findloc; /* offset of last find */
static long hiline; /* offset of highlighted line */
static int igncase = 1; /* NZ if ignoring case in find */
/* function delcarations created by -Zg option - ALTCALL added
NOTE: anything called by menu routine cannot be ALTCALL */
void vfind(int);
static int view_prev(void), view_tof(void), view_eof(void);
int view(void), view_move(int), view_fignore(void), view_fexact(void);
static int view_exit(void), view_down(void), view_up(void), view_next(void);
static int view_right(void), view_left(void), view_set(void), view_goto(void);
static int view_fnxt(void), view_fprv(void), view_fstr(void), view_fopt(void);
static int do_mark(void), setmark(void), gomark(void), ALTCALL view_line(void);
static int view_7bit(void), view_8bit(void), view_asc(void), view_hex(void);
static int ALTCALL nsol(void), ALTCALL more2view(void);
static int ALTCALL align(void), ALTCALL backup(int), ALTCALL peol(void);
static int ALTCALL fmt_asc_line(char *,int *), ALTCALL fmt_hex_line(char *,int *);
static struct key_ent { /* table mapping movement keys to functions */
int key;
int (*func)();
} key2func[] = { { DOWN, view_next }, { UP, view_prev }, { PGDN, view_down },
{ PGUP, view_up }, { HOME, view_tof }, { END, view_eof },
{ RIGHT, view_right }, { LEFT, view_left } };
#define NMOVKEYS (8)
extern MENU_STATE curmenu;
extern MENU top_file_menu[], *top_menu;
static char setgo[] = "Set/Goto marker";
static MENU fopt_menu[] = {
{ "Ignore", "Ignore case when searching", view_fignore, NULL },
{ "Exact", "Match case of string when searching", view_fexact, NULL },
{ NULL, NULL, NULL, NULL }
};
static MENU find_menu[] = {
{ "Next", "Find next occurance", view_fnxt, NULL },
{ "Prev", "Find previous occurance", view_fprv, NULL },
{ "String", "Set string to find", view_fstr, NULL },
{ "Options", "Set find options", NULL, fopt_menu },
{ NULL, NULL, NULL, NULL }
};
static MENU mark_menu[] = {
{ "1", setgo, do_mark, NULL },
{ "2", setgo, do_mark, NULL },
{ "3", setgo, do_mark, NULL },
{ "4", setgo, do_mark, NULL },
{ "5", setgo, do_mark, NULL },
{ NULL, NULL, NULL, NULL }
};
MENU top_view_menu[] = {
{ "Dwn", "Page down in the file", view_down, NULL },
{ "Up", "Page up in the file", view_up, NULL },
{ "Nxt", "Advance one line", view_next, NULL },
{ "Prv", "Backup one line", view_prev, NULL },
{ "Rght", "Scroll right 8 characters", view_right, NULL },
{ "Left", "Scroll left 8 characters", view_left, NULL },
{ "TOF", "Goto Top Of File", view_tof, NULL },
{ "EOF", "Goto End Of File", view_eof, NULL },
{ "Set", "Set marker at current position", view_set, mark_menu },
{ "Goto", "Goto set marker position", view_goto, mark_menu },
{ "Find", "Find string", NULL, find_menu },
{ "Asc", "Display file in ASCII", view_asc, NULL },
{ "Hex", "Display file in hex", view_hex, NULL },
{ "7b", "Display 7 bits per character", view_7bit, NULL },
{ "8b", "Display 8 bits per character", view_8bit, NULL },
{ "Quit", "Return to file display", view_exit, top_file_menu },
{ NULL, NULL, NULL, NULL }
};
extern WINDOW cw;
extern char *cantopen;
extern FILE_ENT files[];
extern unsigned char view_display, restricted;
int ALTCALL vbuf_init(int ); /* declarations for buffer routines */
int ALTCALL vbuf_free(void);
unsigned long ALTCALL vtell(void);
int ALTCALL vseek(int ,long ), ALTCALL vnextch(int ), ALTCALL vprevch(int );
#define view_seek(off) vseek(inf,off)
/******************************************************************************
** V I E W **
*****************************************************************************/
view() { /* view the current file at the terminal */
int i;
register char *fn;
register FILE_ENT *fp;
/* don't try to view file if its empty */
fp = &files[cw.curidx]; /* a couple of quick pointers */
if (fp->size == 0)
show_error(0,EMPTY_FILE,1,"This file is empty!");
bitmask = 0xff; /* defaults: 8 bit, ascii, left edge */
ascmode = TRUE;
margin = 0;
/* open the file to be viewed, error out if can't open */
if ((inf = open((fn = fname(fp)),O_RDONLY|O_BINARY)) == -1) {
free(fn);
show_error(SHOW_DOS,CANT_OPEN,3,cantopen,fp->name,": ");
}
savescreen(); /* save current display image */
restricted = TRUE; /* disable special file commands */
view_display = TRUE; /* yes, we are viewing */
for (i = 0; i < 5; i++) /* set markers to TOF */
markers[i] = 0L;
hiline = findloc = -1L; /* indicate no finds/no highlighted lines yet */
vbuf_init(inf); /* initialize view buffer system */
center_text(FIRST_VROW-1,fn); /* show file name */
free(fn);
view_down(); /* display the first screen of file data */
top_menu = top_view_menu; /* setup the view menu as the main menu */
}
/******************************************************************************
** V I E W _ E X I T **
*****************************************************************************/
static int
view_exit() { /* exit the view display, return to file display */
close(inf); /* close file */
vbuf_free(); /* release memory */
top_menu = top_file_menu; /* restore file menu as main */
restricted = FALSE; /* all commands are enabled */
view_display = FALSE; /* not viewing */
restorescreen(); /* redisplay prior screen image */
}
/******************************************************************************
** V I E W _ D O W N **
*****************************************************************************/
static int
view_down() { /* page down into the view buffer/file */
register int i;
if (!more2view()) /* nothing to do if no more data to view */
return;
nlines = 0; /* no lines displayed yet */
tos = vtell(); /* remember where top of screen is */
/* display up to a screen full of file data, clear the screen as we go */
for (i = 0; i < VIEW_ROWS; i++) {
gotorc(i+FIRST_VROW,0); /* position to line */
if (view_line()) /* display a single line */
nlines++; /* count lines displayed */
}
}
/******************************************************************************
** V I E W _ U P **
*****************************************************************************/
static int
view_up() { /* page up into the view buffer */
long curoff;
/* back two screen's worth, or to the top line in memory and use
view_down() to display the screen - only display if we really
backed up (might be at TOF) */
curoff = vtell(); /* where we were */
view_seek(tos); /* quickly to top of screen */
if (backup(VIEW_ROWS)) /* try to backup another screen */
view_down(); /* display prior screen if backed up */
else
view_seek(curoff); /* must be tof, back to where we were */
}
/******************************************************************************
** V I E W _ N E X T **
*****************************************************************************/
static int
view_next() { /* display the next line in the buffer/file */
long curoff;
if (!more2view()) /* nothing to do if no more data to view */
return;
/* set the new top of screen location */
if (ascmode) { /* ascii mode display? */
curoff = vtell(); /* save where we are */
view_seek(tos); /* to top of screen */
nsol(); /* to start of next line */
tos = vtell(); /* its the new top of screen */
view_seek(curoff); /* back to bottom of screen */
} else /* hex mode */
tos += 16; /* tos is just the next hex line */
/* scroll the screen up one line to make room for the new line at bottom */
delete_line(FIRST_VROW,VIEW_ROWS-1);
gotorc(FIRST_VROW+VIEW_ROWS-1,0); /* cursor to the last display line */
view_line(); /* display the line */
}
/******************************************************************************
** V I E W _ P R E V **
*****************************************************************************/
static int
view_prev() { /* display the previous line in the buffer */
long curoff;
curoff = vtell(); /* where we are now */
view_seek(tos); /* old top of screen */
if (backup(1)) { /* can we backup another line */
tos = vtell(); /* if so, its new tos */
insert_line(FIRST_VROW+1,VIEW_ROWS-1); /* insert a blank line */
gotorc(FIRST_VROW,0); /* cursor to first line */
view_line(); /* display the line */
view_seek(curoff); /* back to old bottom */
if (nlines < VIEW_ROWS) /* is a full screen displayed? */
nlines++; /* no, one more displyed now */
else
backup(1); /* yes, back one line */
} else /* couldn't backup, must be tof */
view_seek(curoff);
}
/******************************************************************************
** V I E W _ T O F **
*****************************************************************************/
static int
view_tof() { /* backup and display the top of the file */
view_seek(0L); /* just go to top of file */
view_down(); /* and display a screen */
}
/******************************************************************************
** V I E W _ E O F **
*****************************************************************************/
static int
view_eof() { /* display the end of the file */
view_seek(files[cw.curidx].size); /* seek to eof */
backup(VIEW_ROWS); /* backup a screen full */
view_down(); /* display a screen full */
}
/******************************************************************************
** V I E W _ M O V E **
*****************************************************************************/
view_move(mov_cmd) /* move around the view buffer/file in response to */
int mov_cmd; /* single key commands when viewing a file */
{
register int i;
/* basically, we just map the special keys to the same functions
performed by the menu options */
for (i = 0; i < NMOVKEYS; i++)
if (mov_cmd == key2func[i].key) {
(*key2func[i].func)();
break;
}
}
/*****************************************************************************
V I E W _ S E T / G O T O / M A R K
*****************************************************************************/
static int
view_set() { /* prepare to set a marker to current position */
mark_func = setmark; /* use the setmark routine later */
}
static int
view_goto() { /* prepare to goto a marker position */
mark_func = gomark; /* use the gomark routine later */
}
static int
do_mark() { /* set or goto a marker position */
(*mark_func)();
}
static int
setmark() { /* set a marker position */
markers[curmenu.current_selection] = tos;
}
static int
gomark() { /* goto a marker position */
tos = markers[curmenu.current_selection]; /* where tos should be */
align(); /* start at begining of line */
view_down(); /* display screen full */
}
/*****************************************************************************
V I E W _ F N X T / P R V / I G N O R E / E X A C T
*****************************************************************************/
static int
view_fnxt() { /* find the string in forward direction */
vfind(1); /* 1 means search forward */
}
static int /* find the string in backward direction */
view_fprv() {
vfind(0); /* 0 means search backward */
}
static int /* ignore case */
view_fignore() {
igncase = 1;
}
static int /* require exact case match */
view_fexact() {
igncase = 0;
}
/**************************************************************************
V F I N D
**************************************************************************/
void
vfind(forward) /* find a string in selected direction */
register int forward;
{
int fch;
long temploc;
register int ch;
char *fcp, nfmsg[11+FSTR_LEN];
if (findstr == NULL)
show_error(0,NO_FND_STR,1,"No find string has been selected");
/* pick where to start the search from - if this is the first find or the
last find location isn't currently displayed, start from the tos (if
going forward) or bottom of screen (if going backward) - otherwise,
start 1 character offset from the last find so we don't find the same
string again. */
if (findloc < 0L || findloc < tos || findloc >= vtell())
findloc = forward ? tos : vtell();
else /* its on the screen - try to offset by 1 */
if (forward && findloc < files[cw.curidx].size) /* going forward */
findloc++;
else
if (!forward && findloc > 0L) /* going backward */
findloc--;
view_seek(findloc); /* move to 1st/last find location */
/* try to find users string in file */
fch = *findstr; /* first char in find string */
while ((ch = forward ? Vnextch(inf) : Vprevch(inf)) != EOF)
/* is this the first char of the search string? */
if (ch == fch || igncase && tolower(ch) == tolower(fch)) {
temploc = vtell(); /* could be it, remember where we are */
/* does the rest of the string match? */
if (!forward) /* adjust if we are searching backward */
vnextch(inf);
for (fcp = findstr+1; *fcp; fcp++) /* check rest of string */
if ((ch = vnextch(inf)) != *fcp)
if (!igncase || tolower(ch) != tolower(*fcp))
break;;
if (*fcp == '\0') /* ***** FOUND IT ***** */
break;
view_seek(temploc); /* not yet, back to where we were */
}
if (ch == EOF) { /* EOF if wasn't found */
findloc = hiline = -1L; /* don't highlight any lines */
strcpy(nfmsg,"Not found: "); /* tell user it wasn't found */
strcat(nfmsg,findstr);
show_error(QUIET,0,1,nfmsg);
view_current(); /* make sure no highlighted line */
} else { /* ******* F O U N D I T ******** */
tos = findloc = temploc - forward;/* remember where string is */
align(); /* goto start of that line */
hiline = vtell(); /* highlight this line */
backup(VIEW_ROWS >> 1); /* try to center line w/str */
view_down(); /* view screen */
}
}
/***************************************************************************
V I E W _ F S T R
***************************************************************************/
static int
view_fstr() { /* pick the string to find */
char *str;
str = prompt("Select Find String","Enter string to find: ",findstr,0,FSTR_LEN);
if (strlen(str) == 0)
return;
if (findstr) /* release old find string */
free(findstr);
findstr = Strdup(str); /* make local copy of string */
}
/*****************************************************************************
V I E W _ L I N E
*****************************************************************************/
static int ALTCALL
view_line() { /* display a single line of the file */
int col, ch, hl = 0;
char line[SCREEN_COLS+1];
if (hl = (hiline == vtell())) /* highlight this line if desired */
setvattrib(DIS_HIGH);
if (ascmode) /* format line as ascii or hex data */
ch = fmt_asc_line(line,&col);
else
ch = fmt_hex_line(line,&col);
disp_str(line); /* make one call to display line */
if (col < margin+SCREEN_COLS) /* clear if < full line displayed */
clr_eol();
if (hl) /* alwasy go back to normal */
setvattrib(DIS_NORM);
return(ch != EOF || col); /* return true if something displayed */
}
/*****************************************************************************
F M T _ A S C _ L I N E
****************************************************************************/
static int ALTCALL
fmt_asc_line(op,colp) /* format an ascii line for display */
char *op;
int *colp;
{
register int ch, col = 0;
int i, endcol = margin + SCREEN_COLS;
while ((ch = Vnextch(inf)) != EOF && (ch = ch & bitmask) != '\n')
if (ch == '\t') {
for (i = 8 - (col & 7); i; i--, col++)
if (col >= margin && col < endcol)
*op++ = ' ';
} else
if (ch != '\r' && ch != '\0') {
if (col >= margin && col < endcol)
*op++ = ch;
col++;
}
*op = '\0'; /* null terminate it for disp_str */
*colp = col; /* tell caller the # cloumns */
return(ch); /* and if EOF was reached */
}
/******************************************************************************
F M T _ H E X _L I N E
*****************************************************************************/
static int ALTCALL
fmt_hex_line(op,colp) /* format a hex line for later display */
register char *op;
int *colp;
{
int ch, ach, j;
register int i;
char offstr[9], *ap;
static char bin2hex[] = "0123456789ABCDEF";
/* test if there is anything to format */
if (vnextch(inf) == EOF) {
*colp = 0;
*op = '\0';
return(EOF);
} else
vprevch(inf);
/* format data offset into buffer */
ultoa(vtell(),offstr,16); /* offset to hex */
j = strlen(offstr);
for (i = 6 - j; i > 0; i--) /* zero fill */
*op++ = '0';
if (j <= 6) /* don't use more than 6 digits */
strcpy(op,offstr);
else
strcpy(op,offstr+j-6);
strupr(op); /* ultoa leaves A-F in lower case */
strcat(op," "); /* go beyond the offset */
op += strlen(op);
ap = op + 53; /* where ascii data starts */
*ap++ = V_bar; /* might as well do it now */
/* setup data in hex (and ascii) */
for (i = 16; i; i--) { /* at most 16 bytes to fmt */
ch = Vnextch(inf); /* next char from file */
if (ch == EOF) /* done? */
break;
*op++ = bin2hex[(ch >> 4) & 0x0f]; /* hexalate it */
*op++ = bin2hex[ch & 0x0f];
*op++ = ' ';
if (((i+3) & 3) == 0) /* extra spacer every 4 bytes */
*op++ = ' ';
if ((ach = ch & bitmask) < ' ') /* do the ascii char, '.' if ctrl ch */
*ap++ = '.';
else
*ap++ = ach;
}
/* blank fill if EOF was reached */
for ( ; i; i--) { /* i is # chars to blank fill */
strncpy(op," ",3);
op += 3;
if (((i+3) & 3) == 0)
*op++ = ' ';
*ap++ = ' ';
}
*op++ = ' '; /* up to ascii data */
*ap++ = V_bar; /* closing bar at end */
*ap = '\0'; /* The Terminator */
*colp = 74; /* tell call how many columns */
return(ch); /* and if EOF was reached */
}
/*****************************************************************************
V I E W _ R I G H T / L E F T
*****************************************************************************/
static int
view_right() { /* scroll right 8 characters */
margin += 8;
view_current();
disp_margin();
}
static int
view_left() { /* scroll left 8 characters */
if (margin >= 8) {
margin -= 8;
view_current();
disp_margin();
}
}
static int
disp_margin() { /* display the viewing margins */
char marstr[11];
if (margin) {
itoa(margin,marstr,10);
disp_msg(2,"COL: ",marstr);
} else /* must have just gone to 0 */
clr_msg();
}
/*****************************************************************************
V I E W _ n B I T
*****************************************************************************/
static int
view_7bit() { /* display data using low order 7 bits */
if (bitmask != 0x7f) {
bitmask = 0x7f;
view_current();
}
}
static int
view_8bit() { /* display data using all 8 bits per char */
if (bitmask != 0xff) {
bitmask = 0xff;
view_current();
}
}
static int
view_current() { /* redisplay the current screen */
view_seek(tos);
view_down();
}
/*****************************************************************************
V I E W _ A S C
*****************************************************************************/
static int
view_asc() { /* set ascii mode display */
if (!ascmode) { /* only need to change if in hex mode */
ascmode = TRUE; /* set ascii mode */
align(); /* make sure were at begining of line */
view_down(); /* redisplay in ascii format */
}
}
/*****************************************************************************
V I E W _ H E X
*****************************************************************************/
static int
view_hex() { /* set hex mode display */
if (ascmode) { /* only need to change if in ascii mode */
ascmode = FALSE; /* set hex mode */
align(); /* make sure were at begining of line */
view_down(); /* redisplay in ascii format */
}
}
/*****************************************************************************
A L I G N
*****************************************************************************/
static int ALTCALL
align() { /* align tos to be at the start of a line */
if (ascmode) { /* ascii mode? */
view_seek(tos); /* backup to current top of screen */
if (backup(1)) /* make sure were at the start of */
nsol(); /* the current line */
} else { /* hex mode */
tos &= ~((long) 0x0f); /* force a paragraph boundry */
view_seek(tos); /* backup to current top of screen */
}
}
/*****************************************************************************
B A C K U P
*****************************************************************************/
static int ALTCALL
backup(todo) /* backup todo lines from current position */
int todo;
{
register int i;
int part, bytes;
unsigned long off, lines;
/* backup in hex mode */
if (!ascmode) { /* different if in hex mode */
off = vtell(); /* current loc in file */
lines = off >> 4; /* # full hex display lines above */
part = (bytes = off & (long) 0x0f) > 0; /* may be partial line if at eof */
if (todo > lines + part) { /* more todo than are? */
view_seek(0L); /* just goto tof */
return(lines + part); /* went back this # lines */
} else {
view_seek(off - (((todo - part) << 4)+bytes)); /* backup todo lines */
return(todo);
}
}
/* backup in ascii mode */
/* special case backing up from EOF - there may or may not be a \n
at the end of the last line */
if (vnextch(inf) == EOF) { /* at end of file? */
vprevch(inf); /* always backup at least one char */
i = 1; /* we will backup 1 line here */
if (peol() == '\n') /* goto start of prev line */
vnextch(inf);
} else { /* not at EOF, setup for loop down below */
i = 0;
vprevch(inf);
}
/* backup todo ascii lines, 1 line may have been done above */
for ( ; i < todo; i++) {
if (peol() == EOF) /* goto end of prev line */
break;
if (peol() == '\n') /* end of prev prev line */
vnextch(inf); /* start of prev line */
}
return(i); /* tell caller how many ascii lines backed up */
}
static int ALTCALL
peol() { /* move to end of prev line */
register int ch;
while ((ch = Vprevch(inf)) != '\n' && ch != EOF) ; /* end of prev line */
return(ch);
}
static int ALTCALL
nsol() { /* move to start of next line */
register int ch;
while ((ch = Vnextch(inf)) != '\n' && ch != EOF) ; /* start of next line */
return(ch);
}
/*****************************************************************************
M O R E 2 V I E W
*****************************************************************************/
static int ALTCALL
more2view() { /* return true if more data to view */
return(vtell() < files[cw.curidx].size);
}